//
//  RxFeedbackTest3ViewController.swift
//  iOS-RxSwift-Tutorials_Example
//
//  Created by mengru.tian on 2020/9/24.
//  Copyright © 2020 CocoaPods. All rights reserved.
//

import UIKit
import RxFeedback
import RxCocoa
import RxSwift
import MBProgressHUD

extension RxFeedbackTest3ViewController {
    //响应结果枚举
    enum Result<T, E: Error> {
        case success(T)  //成功（里面是返回的数据）
        case failure(E)  //失败（里面是错误原因）
    }
     
    //失败情况枚举
    enum GitHubServiceError: Error {
        case offline
        case githubLimitReached
    }
    
    typealias SearchRepositoriesResponse = Result<(GitHubRepositories), GitHubServiceError>
     
    class GitHubNetworkService {
         
        //搜索资源数据
        func searchRepositories(query:String) -> Observable<SearchRepositoriesResponse> {
            return GitHubProvider.rx.request(.repositories(query))
                .filterSuccessfulStatusCodes()
                .mapObject(GitHubRepositories.self)
                .map{ .success($0) } //成功返回
                .asObservable()
                .catchError({ error in
                    print("发生错误：",error.localizedDescription)
                    //失败返回（GitHub接口对请求频率有限制，太频繁会被拒绝：403）
                    return Observable.of(.failure(.githubLimitReached))
                })
        }
    }
    //状态
    struct State {
        var search: String? { //搜索的文字
            didSet {
                if search == nil || search!.isEmpty {
                    self.title = "hangge.com"
                    self.loading = false
                    self.results = []
                    return
                }
                self.loading = true
            }
        }
         
        var title: String? //导航栏标题
        var loading: Bool //当前正在加载
        var results: [GitHubRepository] //搜索结果
        var lastError: GitHubServiceError? //错误信息
         
        //返回初始化状态
        static var empty: State {
            return State(search: nil, title: "hangge.com", loading: false,
                         results: [], lastError: nil)
        }
    }
     
    //事件
    enum Event {
        case searchChanged(String)
        case response(SearchRepositoriesResponse)
    }
}
 
//失败枚举对应的错误信息
extension RxFeedbackTest3ViewController.GitHubServiceError {
    var displayMessage: String {
        switch self {
        case .offline:
            return "网络链接失败!"
        case .githubLimitReached:
            return "请求太频繁，请稍后再试!"
        }
    }
}

class RxFeedbackTest3ViewController: UIViewController {
    
    @IBOutlet weak var tableView: UITableView!
    //搜索栏
    var searchBar:UISearchBar!
    
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        title = "64.RxFeedback架构3：GitHub资源搜索样例"
        view.backgroundColor = .white
        
        /**** 数据请求服务 ***/
       let networkService = GitHubNetworkService()
        
       //创建一个重用的单元格
       self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        
       //创建表头的搜索栏
       self.searchBar = UISearchBar(frame: CGRect(x: 0, y: 0,
                                   width: self.view.bounds.size.width, height: 56))
       self.tableView.tableHeaderView =  self.searchBar
        
       //创建一个加载指示器
       let loadingHUD = MBProgressHUD.showAdded(to: self.view, animated: false)

       Driver.system(
           initialState: State.empty,
           reduce: { (state: State, event: Event) -> State in
               switch event {
               case .searchChanged(let search):
                   var result = state
                   result.search = search
                   result.lastError = nil
                   return result
               case .response(.success(let repositories)):
                   var result = state
                   result.results = repositories.items
                   result.title = "共有 \(repositories.totalCount!) 个结果"
                   result.loading = false
                   result.lastError = nil
                   return result
               case .response(.failure(let error)):
                   var result = state
                   result.loading = false
                   result.lastError = error
                   return result
               }
           },
           feedback:
               bind(self) { me, state in
                   let subscriptions = [
                       //搜索结果绑定
                       state.map { $0.results }
                           .drive(me.tableView.rx.items)(me.configureCell),
                       //导航栏标题绑定
                       state.map { $0.title }
                           .drive(me.navigationItem.rx.title),
                       //加载指示器状态绑定
                       state.map { !$0.loading }
                           .drive(loadingHUD.rx.isHidden),
                       //消息指示器状态绑定
                       state.map { $0.lastError }.drive(onNext: { error in
                           if let error = error{
                               print(error.displayMessage)
                               let hud = MBProgressHUD.showAdded(to: self.view,
                                                                 animated: true)
                               hud.mode = .text ////纯文本模式
                               hud.label.text = error.displayMessage
                               hud.removeFromSuperViewOnHide = true //隐藏时从父视图中移除
                               hud.hide(animated: true, afterDelay: 2)  //2秒钟后自动隐藏
                           }
                       })
                   ]
                    
                   let events: [Signal<Event>] = [
                       me.searchBar.rx.text.orEmpty
                           .changed
                           .throttle(1, scheduler: MainScheduler.instance)//间隔超1秒才发
                           .asSignal(onErrorRecover: { _ in .empty() })
                           .map(Event.searchChanged)
                   ]
                    
                   return Bindings(subscriptions: subscriptions, events: events)
               },
           react(request: { $0.search }, effects: { search in
                   if search.isEmpty {
                       return Signal.empty()
                   }
                   return networkService.searchRepositories(query: search)
                       .asSignal(onErrorJustReturn: .failure(.offline))
                       .map(Event.response)
               })
           )
           .drive()
           .disposed(by: disposeBag)
        
       //单元格点击
       tableView.rx.modelSelected(GitHubRepository.self)
           .subscribe(onNext: {[weak self] item in
               //显示资源信息（完整名称和描述信息）
               self?.showAlert(title: item.fullName, message: item.description)
           }).disposed(by: disposeBag)
    }
    //单元格配置
    func configureCell(tableView: UITableView, row: Int, item: GitHubRepository)
        -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
        cell.textLabel?.text = item.name
        cell.detailTextLabel?.text = item.htmlUrl
        return cell
    }
     
    //显示消息
    func showAlert(title:String, message:String){
        let alertController = UIAlertController(title: title,
                                                message: message, preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "确定", style: .cancel, handler: nil)
        alertController.addAction(cancelAction)
        self.present(alertController, animated: true, completion: nil)
    }
}
